package com.zl.gmadmin.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.gmadmin.entity.SysMenu;
import com.zl.gmadmin.entity.SysRole;
import com.zl.gmadmin.mapper.SysRoleMapper;
import com.zl.gmadmin.payload.RoleQueryCriteria;
import com.zl.gmadmin.service.SysRoleService;
import com.zl.gmadmin.service.dto.MenuDto;
import com.zl.gmadmin.utils.Builder;
import com.zl.gmadmin.utils.FileUtil;
import com.zl.gmadmin.utils.LogUtil;
import com.zl.gmadmin.utils.PageUtils;
import com.zl.gmadmin.vo.SelectVo;
import com.zl.gmadmin.vo.menu.SysMenuVo;
import com.zl.gmadmin.vo.role.SysRoleVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangliang
 * @version 1.0
 * @date 2021/2/2 16:01
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    private final SysRoleMapper sysRoleMapper;

    public SysRoleServiceImpl(SysRoleMapper sysRoleMapper) {
        this.sysRoleMapper = sysRoleMapper;
    }

    @Override
    public List<SysRole> selectByUserId(Long id) {
        return sysRoleMapper.selectByUserId(id);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public List<SelectVo> findAllName() {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        List<SysRole> roles = sysRoleMapper.selectList(queryWrapper);
        List<SelectVo> selectVos = new ArrayList<>();
        roles.forEach(sysRole -> {
            SelectVo selectVo = Builder.of(SelectVo::new)
                    .with(SelectVo::setId, sysRole.getId())
                    .with(SelectVo::setLabel, sysRole.getName())
                    .with(SelectVo::setEnabled, false)
                    .build();
            selectVos.add(selectVo);
        });
        return selectVos;
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public Object selectPageVo(RoleQueryCriteria queryCriteria, Page<SysRole> page) {

        QueryWrapper queryWrapper = new QueryWrapper();

        IPage<SysRole> iPage = sysRoleMapper.selectPageVo(page, queryWrapper);


        List<SysRole> sysRoles = iPage.getRecords();
//        LogUtil.debug("返回的信息sysRole:  "+JSONUtil.toJsonStr(sysRoles));

        List<SysRoleVo> sysRoleVos = new ArrayList<>();
//        處理返回的菜單数据
        for (int i = 0; i < sysRoles.size(); i++
        ) {
            SysRole sysRole = sysRoles.get(i);
            List<MenuDto> menuDtoList = sysRole.getMenus().stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());
            SysMenuVo sysMenuVo = new SysMenuVo();
            List<SysMenuVo> menuVos = menuDtoList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());

            SysRoleVo sysRoleVo = Builder.of(SysRoleVo::new)
                    .with(SysRoleVo::setId, sysRole.getId())
                    .with(SysRoleVo::setName, sysRole.getName())
                    .with(SysRoleVo::setLevel, sysRole.getLevel())
                    .with(SysRoleVo::setDescription, sysRole.getDescription())
                    .with(SysRoleVo::setDataScope, sysRole.getDataScope())
                    .with(SysRoleVo::setCreateBy, sysRole.getCreateBy())
                    .with(SysRoleVo::setUpdateBy, sysRole.getUpdateBy())
                    .with(SysRoleVo::setMenus, menuVos)
                    .with(SysRoleVo::setCreateTime, Objects.nonNull(sysRole.getCreateTime()) ? sysRole.getCreateTime() : null)
                    .with(SysRoleVo::setUpdateTime, Objects.nonNull(sysRole.getUpdateTime()) ? sysRole.getUpdateTime() : null)
                    .build();
//            LogUtil.debug("创建日期: "+ sysRoleVo.getCreateTime());

            sysRoleVos.add(sysRoleVo);
        }

//        LogUtil.debug("roles:"+JSONUtil.toJsonStr(sysRoleVos));

        return PageUtils.toPage(sysRoleVos.stream().collect(Collectors.toList()), iPage.getTotal());
    }

    @Override
    public SysRoleVo getByRoleId(Serializable id) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        List<MenuDto> menuDtoList = sysRole.getMenus().stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());
        SysMenuVo sysMenuVo = new SysMenuVo();
        List<SysMenuVo> menuVos = menuDtoList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());


        SysRoleVo sysRoleVo = Builder.of(SysRoleVo::new)
                .with(SysRoleVo::setId, sysRole.getId())
                .with(SysRoleVo::setName, sysRole.getName())
                .with(SysRoleVo::setLevel, sysRole.getLevel())
                .with(SysRoleVo::setDescription, sysRole.getDescription())
                .with(SysRoleVo::setDataScope, sysRole.getDataScope())
                .with(SysRoleVo::setCreateBy, sysRole.getCreateBy())
                .with(SysRoleVo::setUpdateBy, sysRole.getUpdateBy())
                .with(SysRoleVo::setMenus, menuVos)
                .with(SysRoleVo::setCreateTime, Objects.nonNull(sysRole.getCreateTime()) ? sysRole.getCreateTime() : null)
                .with(SysRoleVo::setUpdateTime, Objects.nonNull(sysRole.getUpdateTime()) ? sysRole.getUpdateTime() : null)
                .build();

//        LogUtil.debug("根据id返回: "+JSONUtil.toJsonStr(sysRoleVo));
        return sysRoleVo;
    }

    @Override
    public void download(HttpServletResponse response, List<Long> ids) throws IOException {
        List<SysRole> sysRoles = sysRoleMapper.findAll(ids);
        List<Map<String, Object>> mapList = new ArrayList<>();

        for (SysRole role : sysRoles
        ) {
            Map<String,Object> map=new HashMap<>();
            map.put("角色id",role.getId());
            map.put("角色名称",role.getName());
            map.put("角色等级",role.getLevel());
            map.put("角色描述",role.getDescription());
            map.put("权限范围",role.getDataScope());
            map.put("关联菜单",role.getMenus());
            map.put("创建于",role.getCreateTime());
            map.put("创建时间",role.getCreateTime());
            map.put("更新于",role.getUpdateBy());
            map.put("更新时间",role.getUpdateTime());
            mapList.add(map);
        }

        FileUtil.downloadExcel(mapList, response);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public Boolean addRole(SysRole sysRole, List<SysMenu> menus) {
        sysRoleMapper.insert(sysRole);
        sysRoleMapper.insertRoleConnectedMenus(sysRole.getId(), menus);
        return true;
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public Boolean delRole(Set<Long> ids) {
        sysRoleMapper.deleteBatchIds(ids);
        sysRoleMapper.deleteRoleConnectedMenus(ids);
        sysRoleMapper.deleteRoleConnectedUsers(ids);
        return true;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    @Override
    public Boolean updateRole(SysRole sysRole) {
        sysRoleMapper.updateById(sysRole);
        Set<Long> ids = new HashSet<>();
        ids.add(sysRole.getId());
        sysRoleMapper.deleteRoleConnectedMenus(ids);
        if (sysRole.getMenus().size() > 0) {
            sysRoleMapper.insertRoleConnectedMenus(sysRole.getId(), sysRole.getMenus());
        }
        return true;
    }


}
